package pers.qianyu.service.impl;

import cn.hutool.core.bean.*;
import com.alibaba.excel.*;
import com.alibaba.excel.write.metadata.*;
import lombok.extern.slf4j.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.scheduling.annotation.*;
import org.springframework.stereotype.*;
import pers.qianyu.domain.common.*;
import pers.qianyu.domain.dto.*;
import pers.qianyu.domain.vo.*;
import pers.qianyu.service.*;

import javax.annotation.*;
import java.io.*;
import java.util.*;
import java.util.stream.*;

/**
 * Excel 数据导出服务实现类
 *
 * @author mizzle rain
 * @date 2020-10-14 17:43
 */
@Slf4j
@Service
public class ExcelExportServiceImpl implements ExcelExportService {
    @Resource(name = "localFileServiceImpl")
    private FileService fileService;
    @Autowired
    private UserService userService;

    /**
     * 执行数据库查询
     *
     * @param out          查询结果输出流
     * @param userQueryDTO 查询条件
     */
    private void query(OutputStream out, UserQueryDTO userQueryDTO) {
        // 1. 创建 EasyExcel 导出对象
        ExcelWriter writer = EasyExcelFactory
                .write(out, UserExportDTO.class)
                .build();
        // 2. 分批次加载数据
        userQueryDTO.setPageSize(2);
        int pageNo = 0;
        Pagination<UserVO> pagination;
        do {
            userQueryDTO.setPageNo(++pageNo);
            pagination = userService.query(userQueryDTO);
            log.info("开始导出第 [{}] 页数据", pageNo);
            List<UserExportDTO> userExportDTOList = Optional.ofNullable(pagination.getRecords())
                    .map(List::stream)
                    .orElseGet(Stream::empty)
                    .map(userDTO -> {
                        UserExportDTO userExportDTO = new UserExportDTO();
                        BeanUtil.copyProperties(userDTO, userExportDTO);
                        return userExportDTO;
                    }).collect(Collectors.toList());
            // 3. 导出分批加载的数据
            log.info("完成导出第 [{}] 页数据", pageNo);
            WriteSheet writeSheet = EasyExcelFactory.writerSheet(String.format("第%d页", pageNo)).build();
            writer.write(userExportDTOList, writeSheet);
        } while (pagination.getCurrent() * pagination.getSize() < pagination.getTotal());
        // 4. 收尾工作
        writer.finish();
        log.info("导出数据完成");
    }

    @Override
    public void export(UserQueryDTO userQueryDTO, String fileName) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 1. 实现数据导出到 Excel 中
        query(out, userQueryDTO);
        // 2. 实现文件上传
        ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
        fileService.upload(in, fileName);
    }

    @Async("exportServiceExecutor")
    @Override
    public void asyncExport(UserQueryDTO userQueryDTO, String fileName) {
        export(userQueryDTO, fileName);
    }
}
